﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BoringTodo
{
    public class ScreenShot
    {
        #region Win32 API
        [DllImport("user32.dll")]
        private static extern bool SetProcessDPIAware();

        [DllImport("user32.dll")]
        private static extern int GetSystemMetrics(int nIndex);

        private const int SM_CXSCREEN = 0;
        private const int SM_CYSCREEN = 1;
        #endregion

        private Timer screenshotTimer;
        private readonly string myDocumentsPath;
        private bool isCapturing = false;

        public event EventHandler<string> ScreenshotCaptured;

        public ScreenShot(string myDocumentsPath)
        {
            this.myDocumentsPath = myDocumentsPath;
            
            try
            {
                // 初始化截图计时器
                screenshotTimer = new Timer
                {
                    Enabled = false
                };
                screenshotTimer.Tick += ScreenshotTimer_Tick;
                
                Logger.Log("截图服务初始化完成", LogLevel.Info);
            }
            catch (Exception ex)
            {
                Logger.LogError("截图服务初始化失败", ex);
                MessageBox.Show($"截图服务初始化失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private async void ScreenshotTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                await CaptureAndSaveAsync();
            }
            catch (Exception ex)
            {
                Logger.LogError("自动截图失败", ex);
                MessageBox.Show($"自动截图失败: {ex.Message}", "截图错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public void StartScreenshotTimer(int intervalMinutes)
        {
            try
            {
                if (intervalMinutes <= 0)
                {
                    Logger.Log("截图间隔时间必须大于0，使用默认值60分钟", LogLevel.Warning);
                    intervalMinutes = Constants.DefaultScreenshotInterval;
                }
                
                // 停止现有的计时器（如果正在运行）
                StopScreenshotTimer();
                
                // 设置新的计时器间隔并启动
                screenshotTimer.Interval = intervalMinutes * 60 * 1000; // 转换为毫秒
                screenshotTimer.Start();
                
                Logger.Log($"开始截图计时器，间隔: {intervalMinutes}分钟", LogLevel.Info);
            }
            catch (Exception ex)
            {
                Logger.LogError("启动截图计时器失败", ex);
                MessageBox.Show($"启动截图计时器失败: {ex.Message}", "计时器错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public void StopScreenshotTimer()
        {
            try
            {
                if (screenshotTimer.Enabled)
                {
                    screenshotTimer.Stop();
                    Logger.Log("停止截图计时器", LogLevel.Info);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError("停止截图计时器失败", ex);
                MessageBox.Show($"停止截图计时器失败: {ex.Message}", "计时器错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public async Task<string> CaptureAndSaveAsync()
        {
            // 防止并发截图
            if (isCapturing)
            {
                Logger.Log("已有截图正在进行，跳过本次截图", LogLevel.Warning);
                return null;
            }

            isCapturing = true;
            string screenshotPath = null;
            
            try
            {
                // 确保主应用目录存在
                string appDataPath = Path.Combine(myDocumentsPath, Constants.AppDataFolder);
                if (!Directory.Exists(appDataPath))
                {
                    Directory.CreateDirectory(appDataPath);
                    Logger.Log($"创建应用数据文件夹: {appDataPath}", LogLevel.Info);
                }
                
                // 确保截图主文件夹存在
                string screenshotMainFolder = Path.Combine(appDataPath, Constants.ScreenshotsFolder);
                if (!Directory.Exists(screenshotMainFolder))
                {
                    Directory.CreateDirectory(screenshotMainFolder);
                    Logger.Log($"创建截图主文件夹: {screenshotMainFolder}", LogLevel.Info);
                }
                
                // 创建截图文件夹路径
                DateTime now = DateTime.Now;
                string yearMonthFolder = Path.Combine(screenshotMainFolder, now.ToString("yyyy-MM"));
                if (!Directory.Exists(yearMonthFolder))
                {
                    Directory.CreateDirectory(yearMonthFolder);
                    Logger.Log($"创建年月截图文件夹: {yearMonthFolder}", LogLevel.Info);
                }
                
                string dayFolder = Path.Combine(yearMonthFolder, now.ToString("yyyy-MM-dd"));
                if (!Directory.Exists(dayFolder))
                {
                    Directory.CreateDirectory(dayFolder);
                    Logger.Log($"创建日期截图文件夹: {dayFolder}", LogLevel.Info);
                }

                // 生成文件名，确保唯一性
                string fileName = $"截图_{now.ToString("HH-mm-ss")}.png";
                screenshotPath = Path.Combine(dayFolder, fileName);
                
                // 确保文件夹访问权限
                try
                {
                    // 尝试创建一个临时文件来测试写入权限
                    string testFile = Path.Combine(dayFolder, "test.tmp");
                    File.WriteAllText(testFile, "test");
                    File.Delete(testFile);
                    Logger.Log("验证截图文件夹写入权限成功", LogLevel.Info);
                }
                catch (Exception ex)
                {
                    Logger.LogError($"截图文件夹写入权限测试失败: {ex.Message}", ex);
                    throw new Exception($"无法写入截图文件夹，请检查权限: {ex.Message}", ex);
                }

                // 在单独的线程中进行截图，以避免DPI感知影响UI
                Logger.Log($"开始截图，保存路径: {screenshotPath}", LogLevel.Info);
                await Task.Run(() => CaptureFullScreenDpiAware(screenshotPath));
                
                // 确认文件是否存在
                if (!File.Exists(screenshotPath))
                {
                    throw new Exception($"截图似乎已保存，但文件不存在: {screenshotPath}");
                }
                
                Logger.Log($"截图成功保存: {screenshotPath}, 文件大小: {new FileInfo(screenshotPath).Length} 字节", LogLevel.Info);
                
                // 触发截图完成事件
                ScreenshotCaptured?.Invoke(this, screenshotPath);
                
                return screenshotPath;
            }
            catch (Exception ex)
            {
                Logger.LogError($"截图捕获或保存失败: {ex.Message}", ex);
                MessageBox.Show($"截图失败: {ex.Message}\n\n请检查对 '我的文档\\{Constants.AppDataFolder}\\{Constants.ScreenshotsFolder}' 的访问权限", 
                    "截图错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
            finally
            {
                isCapturing = false;
            }
        }

        private void CaptureFullScreenDpiAware(string savePath)
        {
            bool dpiAwareSet = false;
            try
            {
                // 临时设置DPI感知以获取正确的屏幕分辨率
                dpiAwareSet = SetProcessDPIAware();
                Logger.Log("DPI感知设置成功", LogLevel.Info);
                
                // 获取实际屏幕分辨率
                int screenWidth = GetSystemMetrics(SM_CXSCREEN);
                int screenHeight = GetSystemMetrics(SM_CYSCREEN);
                
                Logger.Log($"获取到屏幕分辨率: {screenWidth}x{screenHeight}", LogLevel.Info);
                
                if (screenWidth <= 0 || screenHeight <= 0)
                {
                    // 如果API调用失败，回退到Screen类
                    Logger.Log("Win32 API获取屏幕分辨率失败，使用Screen类", LogLevel.Warning);
                    screenWidth = Screen.PrimaryScreen.Bounds.Width;
                    screenHeight = Screen.PrimaryScreen.Bounds.Height;
                    Logger.Log($"Screen类获取的屏幕分辨率: {screenWidth}x{screenHeight}", LogLevel.Info);
                }

                if (screenWidth <= 0 || screenHeight <= 0)
                {
                    throw new Exception("无法获取有效的屏幕分辨率");
                }

                using (Bitmap bitmap = new Bitmap(screenWidth, screenHeight))
                {
                    Logger.Log($"创建位图: {screenWidth}x{screenHeight}", LogLevel.Info);
                    
                    using (Graphics graphics = Graphics.FromImage(bitmap))
                    {
                        // 设置高质量图像处理
                        graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                        graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        
                        Logger.Log("开始复制屏幕内容到位图", LogLevel.Info);
                        graphics.CopyFromScreen(0, 0, 0, 0, new Size(screenWidth, screenHeight), CopyPixelOperation.SourceCopy);
                        Logger.Log("屏幕内容复制完成", LogLevel.Info);
                    }
                    
                    try
                    {
                        // 确保目录存在
                        string directory = Path.GetDirectoryName(savePath);
                        if (!Directory.Exists(directory))
                        {
                            Directory.CreateDirectory(directory);
                            Logger.Log($"创建保存目录: {directory}", LogLevel.Info);
                        }
                        
                        // 保存为PNG格式
                        Logger.Log($"开始保存位图到: {savePath}", LogLevel.Info);
                        bitmap.Save(savePath, ImageFormat.Png);
                        Logger.Log($"位图保存成功: {savePath}", LogLevel.Info);
                        
                        // 验证文件是否成功保存
                        if (File.Exists(savePath))
                        {
                            long fileSize = new FileInfo(savePath).Length;
                            Logger.Log($"文件验证: 存在, 大小: {fileSize} 字节", LogLevel.Info);
                        }
                        else
                        {
                            Logger.Log("文件验证失败: 文件不存在", LogLevel.Warning);
                            throw new FileNotFoundException("截图被保存，但文件不存在", savePath);
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError($"保存截图失败: {ex.Message}", ex);
                        throw new Exception($"保存截图失败: {ex.Message}", ex);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError($"DPI感知截图失败: {ex.Message}", ex);
                
                // 尝试不使用DPI感知截图
                try
                {
                    Logger.Log("尝试使用备用截图方法", LogLevel.Info);
                    CaptureFullScreenSimple(savePath);
                }
                catch (Exception innerEx)
                {
                    Logger.LogError($"备用截图方法也失败: {innerEx.Message}", innerEx);
                    throw new Exception($"截图失败: {ex.Message}. 备用方法也失败: {innerEx.Message}", ex);
                }
            }
        }

        private void CaptureFullScreenSimple(string savePath)
        {
            Logger.Log("使用简单方法截图", LogLevel.Info);
            
            try
            {
                // 使用默认的Screen类获取分辨率
                Rectangle bounds = Screen.PrimaryScreen.Bounds;
                Logger.Log($"获取屏幕边界: {bounds.Width}x{bounds.Height}", LogLevel.Info);
                
                if (bounds.Width <= 0 || bounds.Height <= 0)
                {
                    throw new Exception($"无效的屏幕尺寸: {bounds.Width}x{bounds.Height}");
                }
                
                using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
                {
                    Logger.Log($"创建位图: {bounds.Width}x{bounds.Height}", LogLevel.Info);
                    
                    using (Graphics graphics = Graphics.FromImage(bitmap))
                    {
                        Logger.Log("开始屏幕捕获", LogLevel.Info);
                        // 设置高质量图像处理
                        graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                        graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        
                        graphics.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size, CopyPixelOperation.SourceCopy);
                        Logger.Log("屏幕捕获完成", LogLevel.Info);
                    }
                    
                    try
                    {
                        // 确保目录存在
                        string directory = Path.GetDirectoryName(savePath);
                        if (!Directory.Exists(directory))
                        {
                            Directory.CreateDirectory(directory);
                            Logger.Log($"创建保存目录: {directory}", LogLevel.Info);
                        }
                        
                        // 保存为PNG格式
                        Logger.Log($"开始保存位图到: {savePath}", LogLevel.Info);
                        bitmap.Save(savePath, ImageFormat.Png);
                        Logger.Log($"位图保存成功", LogLevel.Info);
                        
                        // 验证文件是否成功保存
                        if (File.Exists(savePath))
                        {
                            long fileSize = new FileInfo(savePath).Length;
                            Logger.Log($"文件验证: 存在, 大小: {fileSize} 字节", LogLevel.Info);
                        }
                        else
                        {
                            Logger.Log("文件验证失败: 文件不存在", LogLevel.Warning);
                            throw new FileNotFoundException("截图看起来已保存，但无法找到文件", savePath);
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError($"保存简单截图失败: {ex.Message}", ex);
                        throw new Exception($"保存截图失败: {ex.Message}", ex);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError($"简单截图失败: {ex.Message}", ex);
                throw new Exception($"简单截图方法失败: {ex.Message}", ex);
            }
        }

        public void Dispose()
        {
            StopScreenshotTimer();
            screenshotTimer?.Dispose();
        }
    }
}
